package com.redhat.auth.domain;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;

import com.dayatang.domain.BaseEntity;
import com.dayatang.domain.InstanceFactory;

/**
 * 帐户
 * 
 * @author chencao
 * 
 */
@Entity
@Table(name = "RAMS_ACCOUNT")
public class Account extends BaseEntity {

	/**
	 * 
	 */
	private static final long serialVersionUID = -321590260221566017L;

	// 账户名
	@NotNull
	@Pattern(regexp="^\\w{2,}$", message="username not match pattern")
	@Column(name = "USERNAME", length = 25, nullable = false)
	
	private String username;

	// 密码
	@NotNull
	@Length(min=6,max=50)
	@Column(name = "PASSWORD", length = 50, nullable = false)
	private String password;

	// 真实姓名
	@Column(name = "REAL_NAME")
	private String realName;

	// 电子邮件
	@Email
	@Column(name = "EMAIL", length = 50, nullable = false)
	private String email;

	// 注册日期
	@NotNull
	@Column(name = "REGISTRY_DATE", nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date registryDate;

	// 是否被锁定
	@NotNull
	@Column(name = "IS_LOCKED", nullable = false)
	private Boolean locked;

	// 最后的密码修改日期
	@NotNull
	@Column(name = "PASSWORD_LAST_UPDATE_DATE", nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date passwordLastUpdateDate;

	// 描述
	@Column(name = "DESCRIPTION", length = 1000)
	private String description;

	@ManyToMany
	@JoinTable(name = "RAMS_ACCOUNT_R_ROLE", joinColumns = { @JoinColumn(name = "ACCOUNT_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
	private Set<Role> roles = new HashSet<Role>();

	
	@ElementCollection
	@CollectionTable(name = "RAMS_BIZ_SYSTEM_BINDING", joinColumns = @JoinColumn(name = "ACCOUNT_ID"))
	private Set<BizSystemBinding> bizSystemBindings = new HashSet<BizSystemBinding>();

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getRealName() {
		return realName;
	}

	public void setRealName(String realName) {
		this.realName = realName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public Date getRegistryDate() {
		return registryDate;
	}

	public void setRegistryDate(Date registryDate) {
		this.registryDate = registryDate;
	}

	public Boolean getLocked() {
		return locked;
	}

	public void setLocked(Boolean locked) {
		this.locked = locked;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Date getPasswordLastUpdateDate() {
		return passwordLastUpdateDate;
	}

	public void setPasswordLastUpdateDate(Date passwordLastUpdateDate) {
		this.passwordLastUpdateDate = passwordLastUpdateDate;
	}

	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	public Set<BizSystemBinding> getBizSystemBindings() {
		return bizSystemBindings;
	}

	public void setBizSystemBindings(Set<BizSystemBinding> bizSystemBindings) {
		this.bizSystemBindings = bizSystemBindings;
	}

	@Override
	public boolean equals(Object arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * lingen.liu 仓储
	 */
	private static AccountRepository accountRepository;

	public static AccountRepository getAccountRepository() {
		if (accountRepository == null) {
			accountRepository = InstanceFactory
					.getInstance(AccountRepository.class);
		}
		return accountRepository;
	}

	public static void setAccountRepositoryRepository(
			AccountRepository accountRepository) {
		Account.accountRepository = accountRepository;
	}

	/**/// ////////////////////领域行为 start/////////////////////////////*/

	/**
	 * 新增帐户
	 */
	public void add() {
		this.setLocked(false);
		this.setRegistryDate(new Date());
		this.setPasswordLastUpdateDate(new Date());
		getAccountRepository().save(this);
	}

	/**
	 * 删除帐户
	 */
	public void remove() {
	    this.setRoles(null);
	    this.setBizSystemBindings(null);
	    update();
		getAccountRepository().remove(this);
	}

	/**
	 * 更新一个帐户
	 */
	public void update() {
		getAccountRepository().save(this);
	}

	/**
	 * 锁定帐户
	 */
	public void disabled() {
		if (this.getLocked() != true) {
			this.setLocked(true);
			getAccountRepository().save(this);
		}
	}

	/**
	 * 解锁帐户
	 */
	public void enabled() {
		if (this.getLocked() != false) {
			this.setLocked(false);
			getAccountRepository().save(this);
		}
	}

	/**
	 * 绑定系统
	 */
	public void bindBizSystem(Set<BizSystemBinding> bizSystemBindings) {
		this.setBizSystemBindings(bizSystemBindings);
		getAccountRepository().save(this);
	}

	/**
	 * 通过Id获取一个帐号
	 * @param id
	 * @return
	 */
	public static Account get(Long id){
		return getAccountRepository().get(id);
	}
	
	/**
	 * 检测是否已存在当前邮箱
	 * @return
	 */
	public static boolean isEmailExist(String email){
		return getAccountRepository().isEmailExist(email);
	}
	
	/**
	 * 检测是否存在当前用户名
	 * @return
	 */
	public static boolean isUsernameExist(String username){
		return getAccountRepository().isUsernameExist(username);
	}
	
	/**
	 * 一个帐号绑定多个系统
	 * @param systems
	 */
	public void bindingBizSystems(String[] systems){
		Set<BizSystemBinding> bizSystemBindings = getBizSystemBindings();
		for(String systemId:systems){
			//获取要绑定的系统
			BizSystem bizSystem= BizSystem.get(Long.parseLong(systemId));
			
			//绑定当前帐号与系统
			BizSystemBinding bizSystemBinding = new BizSystemBinding();
			bizSystemBinding.setBizSystem(bizSystem);
			bizSystemBinding.setStatus(BizSystemBinding.Status.ENABLED);
			if(!bizSystemBindings.contains(bizSystemBinding)){
				bizSystemBindings.add(bizSystemBinding);
			}
		}
		 setBizSystemBindings(bizSystemBindings);
		 update();
	}
	
	/**
	 * 一个帐号同多个系统解除绑定
	 * @param systems
	 */
	public void unBindingBizSystems(String[] systems){
		Set<BizSystemBinding> bizSystemBindings = getBizSystemBindings();
		for(String systemId:systems){
			//获取要绑定的系统
			BizSystem bizSystem= BizSystem.get(Long.parseLong(systemId));
			
			//绑定当前帐号与系统
			BizSystemBinding bizSystemBinding = new BizSystemBinding();
			bizSystemBinding.setBizSystem(bizSystem);
			bizSystemBinding.setStatus(BizSystemBinding.Status.ENABLED);
			if(bizSystemBindings.contains(bizSystemBinding)){
				bizSystemBindings.remove(bizSystemBinding);
			}
		}
		setBizSystemBindings(bizSystemBindings);
		update();
	}
	
	/**
	 * 设置某个帐号关联的某个系统的可用性
	 * @param systemId
	 * @param status
	 */
	public void setSystemStatus(long systemId,BizSystemBinding.Status status){
		Set<BizSystemBinding> bizSystemBindings = getBizSystemBindings();
		for(BizSystemBinding bizSystemBinding:bizSystemBindings){
			BizSystem bizSystem = bizSystemBinding.getBizSystem();
			if(bizSystem.getId().equals(systemId)){
				if(!bizSystemBinding.getStatus().equals(status)){
					bizSystemBinding.setStatus(status);
				}
			}
		}
		update();
	}
	
	/**
	 * 根据用户名获取帐号信息
	 * @param username
	 * @return
	 */
	public static Account get(String username){
		return getAccountRepository().get(username);
	}
}
